package com.xwj.service.Impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xwj.dao.RaRegisterUserDao;
import com.xwj.dto.RegisterUserDto;
import com.xwj.entity.PassWordEntity;
import com.xwj.entity.RaRegisterUser;
import com.xwj.service.Interface.RegisterUserService;
import com.xwj.service.redis.RedisService;
import com.xwj.util.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;

@Slf4j
@Service
@CacheConfig(cacheNames = "RaRegisterUserCache")
public class RegisterUserServiceImpl implements RegisterUserService {

    @Autowired
    private RaRegisterUserDao raRegisterUserDao;
    @Autowired
    private RedisService redisService;

    private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();  //读写锁

    private Lock lock = readWriteLock.readLock();

    public static RegisterUserServiceImpl getInstance() {
        return SpringUtils.getBean(RegisterUserServiceImpl.class);
    }

    @Override
    @Cacheable(key = "#root.methodName+'_'+#pageIndex", unless = "#result.list.size() == 0")
    public PageInfo<RaRegisterUser> findAllUser(int pageIndex, int pageSize) {
        PageHelper.startPage(pageIndex, pageSize);
        lock.lock();
        try {
            List<RaRegisterUser> raRegisterUserList = raRegisterUserDao.findAllUser();
            PageInfo<RaRegisterUser> pageInfo = new PageInfo<>(raRegisterUserList);
            return pageInfo;
        } catch (Exception e) {
            log.error("RegisterUserService异常:", e);
            e.printStackTrace();
            return new PageInfo<>(Collections.emptyList());
        } finally {
            lock.unlock();
        }
    }

    @Override
    @Cacheable(key = "#root.methodName+'_'+#pageIndex+'_'+#registerUserDto.toString()", unless = "#result.list.size() == 0")
    public PageInfo<RaRegisterUser> findUserByProperty(int pageIndex, int pageSize, RegisterUserDto registerUserDto) {
        PageHelper.startPage(pageIndex, pageSize);
        lock.lock();
        try {
            List<RaRegisterUser> raRegisterUserList = raRegisterUserDao.findUserByProperty(registerUserDto);
            PageInfo<RaRegisterUser> pageInfo = new PageInfo<>(raRegisterUserList);
            return pageInfo;
        } catch (Exception e) {
            log.error("RegisterUserService异常:", e);
            e.printStackTrace();
            return new PageInfo<>(Collections.emptyList());
        } finally {
            lock.unlock();
        }
    }

    @Override
    @Cacheable(key = "#root.methodName+'_'+#mail", unless = "#result == null ")
    public RaRegisterUser findUserByMail(String mail) {
        try {
            return raRegisterUserDao.findUserByMail(mail);
        } catch (Exception e) {
            log.error("RegisterUserService异常:", e);
            e.printStackTrace();
            return null;
        }

    }

    @Override
    @Cacheable(key = "#root.methodName+'_'+#phone", unless = "#result == null ")
    public RaRegisterUser findUserByPhone(String phone) {
        try {
            return raRegisterUserDao.findUserByPhone(phone);
        } catch (Exception e) {
            log.error("RegisterUserService异常:", e);
            e.printStackTrace();
            return null;
        }
    }

    @Override
    @Cacheable(key = "#root.methodName+'_'+#id", unless = "#result == null ")
    public RaRegisterUser findUserById(String id) {
        try {
            return raRegisterUserDao.findUserById(id);
        } catch (Exception e) {
            log.error("RegisterUserService异常:", e);
            e.printStackTrace();
            return null;
        }
    }

    @Override
    @Cacheable(key = "#root.methodName+'_'+#id", unless = "#result == null ")
    public PassWordEntity getUserPassWord(String id) {
        try {
            return raRegisterUserDao.getUserPassWord(id);
        } catch (Exception e) {
            log.error("RegisterUserService异常:", e);
            e.printStackTrace();
            return null;
        }
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public int updatePassword(PassWordEntity passWordEntity) {
        try {
            String slat = UUID.randomUUID().toString().substring(0, 8);
            String spwd = new Md5Hash(passWordEntity.getPassword(), slat).toString();
            passWordEntity.setPassword(spwd);
            passWordEntity.setSalt(slat);
            return raRegisterUserDao.updatePassword(passWordEntity);
        } catch (Exception e) {
            log.error("RegisterUserService异常:", e);
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public int addOneRegisterUser(RaRegisterUser raRegisterUser) {
        try {
            return raRegisterUserDao.addOneRegisterUser(raRegisterUser);
        } catch (Exception e) {
            log.error("RegisterUserService异常:", e);
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 异步请求有返回值的用法
     *
     * @param raRegisterUser
     * @return
     */
    @Async("registerTaskAsyncPool")
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public Future<String> addOneRegisterUserSync(RaRegisterUser raRegisterUser) {
        Future<String> future;
        try {
            raRegisterUserDao.addOneRegisterUser(raRegisterUser);
            future = new AsyncResult<>("注册成功");
        } catch (Exception e) {
            log.error("RegisterUserService异常:", e);
            future = new AsyncResult<>("注册失败");
        }
        return future;
    }


    @Override
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public int updateOtherProperty(RaRegisterUser raRegisterUser) {
        try {
            return raRegisterUserDao.updateOtherProperty(raRegisterUser);
        } catch (Exception e) {
            log.error("RegisterUserService异常:", e);
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public int deleteByIds(List<String> list) {
        try {
            return raRegisterUserDao.deleteByIds(list);
        } catch (Exception e) {
            log.error("RegisterUserService异常:", e);
            e.printStackTrace();
            return 0;
        }
    }

    public List<String> parseListId(List<RaRegisterUser> raRegisterUsers) {
        return raRegisterUsers.stream().map(RaRegisterUser::getId).collect(Collectors.toList());
    }

    public void addUrlToRedis(String accressUrl, String key) {
        redisService.set(key, accressUrl, Long.valueOf(3600));
    }

    public String getUrlformRedis(String key) {
        String urlStr = null;
        if (redisService.exists(key))
            urlStr = JSON.parseObject((String) redisService.get(key)).getString("access_url");
        return urlStr;
    }

    public void deleteFromRedis(String key) {
        redisService.remove(key);
    }

}
